查看原文
其他

对遥控装置进行逆向工程——为什么每个工程师都应该学习Python

2018-03-23 爱板网 爱板网

我的遥控原型


最近,我决定恢复我几年前开始的一个旧项目。我有一个高保真音响系统,那是我从过去几年收集的零碎器件拼凑而成的。 我还有一台非常酷的先锋300 CD自动点唱机,Technics唱盘机,Nikko参数均衡器,Denon DRA-295接收机和Harmon / Kardon扬声器。我非常在意在想听的时候能够立即获得高品质的音乐。因为如果我想听一首歌,我想立马就能大声地听到它。


然而,Denon接收器没有红外遥控器。先锋CD播放器也没有。这些设备的遥控器在eBay上是昂贵的,而一些通用遥控器可能支持先锋,但他们不一定会支持Denon。你可以购买与协议无关的高端通用遥控器,并简单地存储频率和时间信息,但转念一想,明明可以自己设计一个,为什么偏要买呢?


第一步是要尝试找到这两台机器的控制代码。如果我手中有遥控器可以工作,我可以进行逆向工程,然而我并没有。话又说回来,如果我有遥控器的话,整个项目就没有必要做了。


大多数红外代码的在线存储库都采用Pronto HEX格式。这基本上是一个巨大的文本文件,每一行都是一个单独的命令。前几个字节描述脉冲的频率,其余字节指定发送该特定代码的开启/关闭时间。如果你对协议一无所知,那么这是一个很好的参考格式,因为它实际上只是存储产生命令所需的脉冲的确切序列;然而,它的代码长度非常没有效率。我为Denon接收器找到的Pronto HEX文件有超过1500行文字! 如果你可以在代码中指定协议,则可以将每个代码存储为无符号的32位变量。它比本来需要的242K文本要小得多!


测试红外LED


但是我们怎样才能从Pronto HEX得到一个无符号的32位整数呢? 如前所述,代码只是保持IR LED开启或关闭的时间量。在Denon使用的协议中,与大多数红外协议一样,这两个数字之间的比率决定了发送的位是0还是1,这很简单——我们只需要剥离标头字节,然后将每对的数字并查看结果以确定二进制输出。但我们这里讨论的可是1500行的内容! 手动做这些工作需要花费数天的时间。 幸运的是,我们有电脑! 我的第一个想法是用C语言编写一个程序,这么说吧,就编程语言来说,C语言就是我的的母语。然而,在C语言中操纵文本和文本文件真的很痛苦。然后我在脑海中立马想到了另一个方案——使用脚本语言!


我最近开始学习Python,它对于这项任务来说似乎很完美。善于处理文本?是的。擅长数学? 确实。Python在技术上具有无限的浮点精度。易于编写并能让我快速地敲代码?也是的。 Python是唯一让我觉得很容易学习的编程语言。很容易上手,特别是如果您有编程经验的话。该语法需要时间漫漫习惯(我个人不喜欢单独使用缩进来分隔代码中的逻辑结构),但是太多已有的模块使得任何任务变得微不足道。作为一名嵌入式程序员,我并不认为Python是一种值得深入研究的语言——相反,我将它视为一种可以自动化解决一般任务的窍门,就像这个项目一样。用25行Python,这个任务几乎是微不足道的。我认为Python非常简单,就像猴子都能看懂,猴子都能写的语言。与功能性或程序语言(如C语言或Java)不同,在开始使用它之前,您不需要花大量时间来理解语言的语法。如果您完全了解任何编程语言,您可以轻松查看其他脚本以及一些在线资源,并立即制作出有用的脚本。


我们来看看它有多简单:


rawcode = open(r"DenonReceiverCodes_stripped.txt", "r")

outputfile = open(r"output_codes_full.txt", "w")

currentline = 0

for line in rawcode:

output = [] #empty list for output

splitline = line.split(" ") #turn the line into a list


#print(splitline)

splitline.remove('\n')

y = 0

for x in list(range(32)): #go through each pair in the line

num1 = int(splitline[y], 16)

num2 = int(splitline[y+1], 16)

if (num2 / num1) == 3:

output.append("0")

elif (num2 / num1) == 7:

output.append("1")

y += 2


#print(output)

outstring = ''.join(output)

outputfile.write(outstring + ",")

outputfile.write("\n")

currentline += 1

print(currentline)

outputfile.flush()

outputfile.close()

rawcode.close()


就是这样! 这非常简单,我们甚至不需要导入任何模块。我们打开输入文件和输出文件,循环输入文件中的每一行,将其转换为Python列表(Python中的一个数据原语),然后执行简单的数学运算将其转换为二进制字符串!然后我们将该输出写入文件,然后关闭这些文件。在这个脚本中,不存在一丁点的缀余代码。这是脚本语言的强大之处,这也是它作为例如C语言这样的低级编程语言最好的伴侣的原因。例如,在嵌套for循环中,请注意我们如何基本上可以从字符串直接转换为整数。试试在C语言中做到这一点!


最终PCB板的3D渲染图


我强烈推荐Mark Lutz编写的Learning Python。它由O'Reilly出版,是一个很好的资源。 我也有Python Pocket Reference,它非常方便。请记住,为了实现上述自动化任务,您实际上并不需要全力以赴! 您不需要了解lambda表达式或生成器函数。只需好好利用已存在的极其丰富和多功能的Python库,并帮助您更快完成工作!我有一个GitHub仓库(链接  https://github.com/MrAureliusR/PythonScripts),其中包含一些我编写的用于自动化或者其他无聊任务的有用地Python脚本。欢迎查看!


原文来自网站Supplyframe-hardware

作者Alexander Rowsell



阅读推荐


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存